package server

import (
	"bufio"
	"encoding/json"
	core "gitee.com/dreamwood/ez"
	"io"
	"net/http"
	"net/url"
	"reflect"
	"strconv"
)

type Input struct {
	Request *http.Request
	Url     string
	UrlData map[string]string
	Json    []byte
	Form    url.Values
}

func NewInput() *Input {
	p := new(Input)
	p.Json = make([]byte, 0)
	return p
}

func GetInputFromRequest(req *http.Request) *Input {
	p := NewInput()
	p.Url = req.URL.Path
	p.Request = req
	var e error
	switch req.Header.Get("Content-Type") {
	case "multipart/form-data":
		e = req.ParseMultipartForm(req.ContentLength)
		p.Form = req.Form
		if e != nil {
			println("ParseMultipartForm", e.Error())
		}
		break
	case "application/x-www-form-urlencoded":
		e = req.ParseForm()
		p.Form = req.Form
		if e != nil {
			println("ParseForm", e.Error())
		}
		break
	case "application/json":
		//处理取得URL中的参数
		e = req.ParseForm()
		p.Form = req.Form
		if e != nil {
			println("ParseForm", e.Error())
		}
		//处理取得Body中的Json数据
		reader := bufio.NewReader(req.Body)
		body := make([]byte, req.ContentLength)
		l, e := io.ReadFull(reader, body)
		if e != nil {
			println("Read", e.Error())
		}
		if int64(l) != req.ContentLength {
			println("数据没有被完整读取")
		}
		p.Json = body
		break
	default:
		e = req.ParseForm()
		p.Form = req.Form
		if e != nil {
			println("ParseForm", e.Error())
		}
	}
	//重新组装数据
	//println(p)
	//tool.JsonLog(p)
	return p
}

func (this *Input) Get(key string) *InputAnyThing {
	null, _ := json.Marshal("")
	find1 := this.GetFromUrl(key)
	str1, _ := json.Marshal(find1.Receive)
	if string(str1) != string(null) {
		return find1
	}
	find2 := this.GetFromGetPost(key)
	str2, _ := json.Marshal(find2.Receive)
	if string(str2) != string(null) {
		return find2
	}
	find3 := this.GetFromJson(key)
	str3, _ := json.Marshal(find3.Receive)
	if string(str3) != string(null) {
		return find3
	}
	return NewInputAnyThing(nil)
}

func (this *Input) GetFromUrl(key string) *InputAnyThing {
	find, ok := this.UrlData[key]
	if !ok {
		return NewInputAnyThing("")
	}
	return NewInputAnyThing(find)
}

func (this *Input) GetFromGetPost(key string) *InputAnyThing {
	return NewInputAnyThing(this.Form.Get(key))
}
func (this *Input) GetFromJson(key string) *InputAnyThing {
	var tmp = make(map[string]interface{})
	e := json.Unmarshal(this.Json, &tmp)
	if e != nil {
		return NewInputAnyThing(nil)
	}
	find, ok := tmp[key]
	if !ok {
		return NewInputAnyThing(nil)
	}
	return NewInputAnyThing(find)
}

func (this *Input) fillModelFromForm(model interface{}) {
	tp := reflect.TypeOf(model)
	jsonData := make(map[string]interface{})
	for i := 0; i < tp.NumField(); i++ {
		field := tp.Field(i)
		//fieldName := field.Name
		switch field.Type.String() {
		case "int", "int64", "int32":
			v := this.Form.Get(core.Lcfirst(field.Name))
			got, e := strconv.ParseInt(v, 10, 64)
			if e != nil {
				println("fillModelFromForm", e.Error())
			}
			jsonData[field.Name] = got
			break
		case "string":
			v := this.Form.Get(core.Lcfirst(field.Name))
			jsonData[field.Name] = v
			break
		case "float", "float64", "float32":
			v := this.Form.Get(core.Lcfirst(field.Name))
			got, e := strconv.ParseFloat(v, 64)
			if e != nil {
				println("fillModelFromForm", e.Error())
			}
			jsonData[field.Name] = got
			break
		case "time.Time":
			v := this.Form.Get(core.Lcfirst(field.Name))
			jsonData[field.Name] = v
			break
		case "bool":
			v := this.Form.Get(core.Lcfirst(field.Name))
			got, e := strconv.ParseBool(v)
			if e != nil {
				println("fillModelFromForm", e.Error())
			}
			jsonData[field.Name] = got
			break
		}
	}
}
